﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
//
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
//
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
//
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
//
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Neto.Core;
/// <summary>
/// 敏感词服务
/// </summary>
public class SensitiveWordService : ISensitiveWordService
{
    private static readonly ConcurrentDictionary<int, List<SysSensitiveWord>> _cachedWords = new();
    private readonly ISqlSugarClient _db;

    private readonly object _lock = new object();
    private bool _isInitialized = false;

    public SensitiveWordService(ISqlSugarClient db)
    {
        _db = db;
        //LoadAllWords(); // 启动时加载一次
    }

    /// <summary>
    /// 确保数据已加载（线程安全）
    /// </summary>
    private void EnsureInitialized()
    {
        if (_isInitialized) return;

        lock (_lock)
        {
            if (_isInitialized) return;

            LoadAllWords();
            _isInitialized = true;
        }
    }

    /// <summary>
    /// 加载所有敏感词到内存
    /// </summary>
    public void LoadAllWords()
    {
        var words = _db.Queryable<SysSensitiveWord>().Where(it => it.IsEnable == true).ToList();
        _cachedWords.Clear();

        foreach (var group in words.GroupBy(w => w.SeverityLevel))
        {
            _cachedWords.TryAdd(group.Key, group.ToList());
        }
    }



    /// <summary>
    /// 替换文本中的敏感词
    /// </summary>
    /// <param name="input"></param>
    /// <param name="replaceChar"></param>
    /// <param name="minSeverity"></param>
    /// <param name="defaultMode"></param>
    /// <returns></returns>
    public string ReplaceSensitiveWords(string input, char replaceChar, int minSeverity, MatchMode defaultMode)
    {
        if (string.IsNullOrEmpty(input)) return input;


        // 确保数据已加载
        EnsureInitialized();


        var sb = new StringBuilder(input);
        var words = GetWordsBySeverity(minSeverity);

        foreach (var word in words)
        {
            string sensitiveWord = word.Word;
            var wordMatchMode = (MatchMode)word.MatchMode;

            // 使用数据库中的匹配模式，若未指定则用默认模式
            var actualMode = wordMatchMode != MatchMode.Default ?
                wordMatchMode : defaultMode;

            if (actualMode == MatchMode.Exact)
            {
                if (input.Equals(sensitiveWord, StringComparison.OrdinalIgnoreCase))
                {
                    return new string(replaceChar, input.Length);
                }
            }
            else // 模糊匹配
            {
                int index = -1;
                while ((index = input.IndexOf(
                    sensitiveWord,
                    index + 1,
                    StringComparison.OrdinalIgnoreCase)) >= 0)
                {
                    sb.Remove(index, sensitiveWord.Length);
                    sb.Insert(index, new string(replaceChar, sensitiveWord.Length));
                }
            }
        }
        return sb.ToString();
    }

    private List<SysSensitiveWord> GetWordsBySeverity(int minSeverity)
    {
        return Enumerable.Range(minSeverity, 4 - minSeverity)
            .SelectMany(level => _cachedWords.TryGetValue(level, out var words) ?
                words : Enumerable.Empty<SysSensitiveWord>())
            .ToList();
    }
}

public enum MatchMode
{
    /// <summary>
    /// 使用数据库设置
    /// </summary>
    Default = -1,
    /// <summary>
    /// 精确匹配
    /// </summary>
    Exact = 0,
    /// <summary>
    /// 模糊匹配
    /// </summary>
    Fuzzy = 1
}

public interface ISensitiveWordService
{
    /// <summary>
    /// 重载所有关键词
    /// </summary>
    void LoadAllWords();
}
